﻿// -----------------------------------------------------------------------
// Copyright (c) David Kean. All rights reserved.
// -----------------------------------------------------------------------
extern alias pcl;
using System;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using pcl::System;

namespace Portable.Reflection
{
    [TestClass]
    public class ReflectionExtensionTests
    {
        [TestMethod]
        public void AsCustomAttributeProvider1_NullAsAssembly_ThrowsArgumentNull()
        {
            ExceptionAssert.ThrowsArgumentNull("assembly", () =>
            {
                ReflectionExtensions.AsCustomAttributeProvider((Assembly)null);
            });
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_CallsAssemblyGetCustomAttributes1()
        {
            int callCount = 0;
            var member = AssemblyFactory.OverrideGetCustomAttributes((inherit) => { callCount++; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_CallsAssemblyGetCustomAttributes2()
        {
            int callCount = 0;
            var member = AssemblyFactory.OverrideGetCustomAttributes((type, inherit) => { callCount++; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_CallsAssemblyIsDefined()
        {
            int callCount = 0;
            var member = AssemblyFactory.OverrideIsDefined((type, inherit) => { callCount++; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_TrueAsInherit_PassesTrueAsInheritToAssemblyGetCustomAttributes1()
        {
            bool? result = null;
            var member = AssemblyFactory.OverrideGetCustomAttributes((inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_FalseAsInherit_PassesFalseAsInheritToAssemblyGetCustomAttributes1()
        {
            bool? result = null;
            var member = AssemblyFactory.OverrideGetCustomAttributes((inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_TrueAsInherit_PassesTrueAsInheritToAssemblyGetCustomAttributes2()
        {
            bool? result = null;
            var member = AssemblyFactory.OverrideGetCustomAttributes((type, inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_FalseAsInherit_PassesFalseAsInheritToAssemblyGetCustomAttributes2()
        {
            bool? result = null;
            var member = AssemblyFactory.OverrideGetCustomAttributes((type, inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_TrueAsInherit_PassesTrueAsInheritToAssemblyIsDefined()
        {
            bool? result = null;
            var member = AssemblyFactory.OverrideIsDefined((type, inherit) => { result = inherit; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_FalseAsInherit_PassesFalseAsInheritToAssemblyIsDefined()
        {
            bool? result = null;
            var member = AssemblyFactory.OverrideIsDefined((type, inherit) => { result = inherit; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_ValueAsAttributeType_PassesValueAsAttributeTypeToAssemblyGetCustomAttributes2()
        {
            Type result = null;
            var member = AssemblyFactory.OverrideGetCustomAttributes((type, inherit) => { result = type; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(typeof(Attribute), result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_ValueAsAttributeType_PassesValueAsAttributeTypeToAssemblyIsDefined()
        {
            Type result = null;
            var member = AssemblyFactory.OverrideIsDefined((type, inherit) => { result = type; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(typeof(Attribute), result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_ReturnsResultOfAssemblyGetCustomAttributes1()
        {
            object[] returnValue = new object[0];
            var member = AssemblyFactory.OverrideGetCustomAttributes((inherit) => { return returnValue; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            var result = provider.GetCustomAttributes(true);

            Assert.AreSame(returnValue, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_ReturnsResultOfAssemblyGetCustomAttributes2()
        {
            object[] returnValue = new object[0];
            var member = AssemblyFactory.OverrideGetCustomAttributes((type, inherit) => { return returnValue; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            var result = provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreSame(returnValue, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_ReturnsResultOfAssemblyIsDefined()
        {
            foreach (var returnValue in new[] { true, false })
            {
                var member = AssemblyFactory.OverrideIsDefined((type, inherit) => { return returnValue; });

                var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
                var result = provider.IsDefined(typeof(Attribute), true);

                Assert.AreEqual(returnValue, result);
            }
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_NullAsMember_ThrowsArgumentNull()
        {
            ExceptionAssert.ThrowsArgumentNull("member", () =>
            {
                ReflectionExtensions.AsCustomAttributeProvider((MemberInfo)null);
            });
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_CallsMemberGetCustomAttributes1()
        {
            int callCount = 0;
            var member = MemberInfoFactory.OverrideGetCustomAttributes((inherit) => { callCount++; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_CallsMemberGetCustomAttributes2()
        {
            int callCount = 0;
            var member = MemberInfoFactory.OverrideGetCustomAttributes((type, inherit) => { callCount++; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_CallsMemberIsDefined()
        {
            int callCount = 0;
            var member = MemberInfoFactory.OverrideIsDefined((type, inherit) => { callCount++; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_TrueAsInherit_PassesTrueAsInheritToMemberGetCustomAttributes1()
        {
            bool? result = null;
            var member = MemberInfoFactory.OverrideGetCustomAttributes((inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_FalseAsInherit_PassesFalseAsInheritToMemberGetCustomAttributes1()
        {
            bool? result = null;
            var member = MemberInfoFactory.OverrideGetCustomAttributes((inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_TrueAsInherit_PassesTrueAsInheritToMemberGetCustomAttributes2()
        {
            bool? result = null;
            var member = MemberInfoFactory.OverrideGetCustomAttributes((type, inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_FalseAsInherit_PassesFalseAsInheritToMemberGetCustomAttributes2()
        {
            bool? result = null;
            var member = MemberInfoFactory.OverrideGetCustomAttributes((type, inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_TrueAsInherit_PassesTrueAsInheritToMemberIsDefined()
        {
            bool? result = null;
            var member = MemberInfoFactory.OverrideIsDefined((type, inherit) => { result = inherit; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_FalseAsInherit_PassesFalseAsInheritToMemberIsDefined()
        {
            bool? result = null;
            var member = MemberInfoFactory.OverrideIsDefined((type, inherit) => { result = inherit; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_ValueAsAttributeType_PassesValueAsAttributeTypeToMemberGetCustomAttributes2()
        {
            Type result = null;
            var member = MemberInfoFactory.OverrideGetCustomAttributes((type, inherit) => { result = type; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(typeof(Attribute), result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_ValueAsAttributeType_PassesValueAsAttributeTypeToMemberIsDefined()
        {
            Type result = null;
            var member = MemberInfoFactory.OverrideIsDefined((type, inherit) => { result = type; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(typeof(Attribute), result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_ReturnsResultOfMemberGetCustomAttributes1()
        {
            object[] returnValue = new object[0];
            var member = MemberInfoFactory.OverrideGetCustomAttributes((inherit) => { return returnValue; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            var result = provider.GetCustomAttributes(true);

            Assert.AreSame(returnValue, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_ReturnsResultOfMemberGetCustomAttributes2()
        {
            object[] returnValue = new object[0];
            var member = MemberInfoFactory.OverrideGetCustomAttributes((type, inherit) => { return returnValue; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            var result = provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreSame(returnValue, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_ReturnsResultOfMemberIsDefined()
        {
            foreach (var returnValue in new[] { true, false })
            {
                var member = MemberInfoFactory.OverrideIsDefined((type, inherit) => { return returnValue; });

                var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
                var result = provider.IsDefined(typeof(Attribute), true);

                Assert.AreEqual(returnValue, result);
            }
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_NullAsParameter_ThrowsArgumentNull()
        {
            ExceptionAssert.ThrowsArgumentNull("parameter", () =>
            {
                ReflectionExtensions.AsCustomAttributeProvider((ParameterInfo)null);
            });
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_GetCustomAttributes1_CallsParameterGetCustomAttributes1()
        {
            int callCount = 0;
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((inherit) => { callCount++; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_GetCustomAttributes2_CallsParameterGetCustomAttributes2()
        {
            int callCount = 0;
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((type, inherit) => { callCount++; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_IsDefined_CallsParameterIsDefined()
        {
            int callCount = 0;
            var member = ParameterInfoFactory.OverrideIsDefined((type, inherit) => { callCount++; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(1, callCount);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_GetCustomAttributes1_TrueAsInherit_PassesTrueAsInheritToParameterGetCustomAttributes1()
        {
            bool? result = null;
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_GetCustomAttributes1_FalseAsInherit_PassesFalseAsInheritToParameterGetCustomAttributes1()
        {
            bool? result = null;
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_GetCustomAttributes2_TrueAsInherit_PassesTrueAsInheritToParameterGetCustomAttributes2()
        {
            bool? result = null;
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((type, inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_GetCustomAttributes2_FalseAsInherit_PassesFalseAsInheritToParameterGetCustomAttributes2()
        {
            bool? result = null;
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((type, inherit) => { result = inherit; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_IsDefined_TrueAsInherit_PassesTrueAsInheritToParameterIsDefined()
        {
            bool? result = null;
            var member = ParameterInfoFactory.OverrideIsDefined((type, inherit) => { result = inherit; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_IsDefined_FalseAsInherit_PassesFalseAsInheritToParameterIsDefined()
        {
            bool? result = null;
            var member = ParameterInfoFactory.OverrideIsDefined((type, inherit) => { result = inherit; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), false);

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_GetCustomAttributes2_ValueAsAttributeType_PassesValueAsAttributeTypeToParameterGetCustomAttributes2()
        {
            Type result = null;
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((type, inherit) => { result = type; return null; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreEqual(typeof(Attribute), result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider3_IsDefined_ValueAsAttributeType_PassesValueAsAttributeTypeToParameterIsDefined()
        {
            Type result = null;
            var member = ParameterInfoFactory.OverrideIsDefined((type, inherit) => { result = type; return false; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            provider.IsDefined(typeof(Attribute), true);

            Assert.AreEqual(typeof(Attribute), result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes1_ReturnsResultOfParameterGetCustomAttributes1()
        {
            object[] returnValue = new object[0];
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((inherit) => { return returnValue; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            var result = provider.GetCustomAttributes(true);

            Assert.AreSame(returnValue, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_GetCustomAttributes2_ReturnsResultOfParameterGetCustomAttributes2()
        {
            object[] returnValue = new object[0];
            var member = ParameterInfoFactory.OverrideGetCustomAttributes((type, inherit) => { return returnValue; });

            var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
            var result = provider.GetCustomAttributes(typeof(Attribute), true);

            Assert.AreSame(returnValue, result);
        }

        [TestMethod]
        public void AsCustomAttributeProvider2_IsDefined_ReturnsResultOfParameterIsDefined()
        {
            foreach (var returnValue in new[] { true, false })
            {
                var member = ParameterInfoFactory.OverrideIsDefined((type, inherit) => { return returnValue; });

                var provider = ReflectionExtensions.AsCustomAttributeProvider(member);
                var result = provider.IsDefined(typeof(Attribute), true);

                Assert.AreEqual(returnValue, result);
            }
        }
    }
}
